<?php

/**
 * @Author: king
 * @Last Modified by:   king
 * Date: 2018/6/19
 * Time: 14:30
 */

namespace App\Http\Controllers\Api\v1\Pay;


use App\Http\Controllers\Api\BaseController;
use App\Tools\Orders as OrdersLib;
use think\Log;
use \Alipay\AopClient;
use \Alipay\Request\AlipayTradeAppPayRequest as AppPayRequest;
use \Alipay\Request\AlipayTradeWapPayRequest as WapPayRequest;
use \Alipay\Request\AlipayTradeQueryRequest as AppPayQueryRequest;

/**
 * @title 支付宝支付相关接口
 * @desc 支付宝支付
 * @url
 * @version 1.1.1
 * Class Ali
 * @package app\api\controller\v2
 */
class AliController extends BaseController
{
    /**
     * 支付方式模型名称
     * @var array
     */
    private $payTypeModelName = [
        'APP' => '\Alipay\Request\AlipayTradeAppPayRequest',
        'WAP' => '\Alipay\Request\AlipayTradeWapPayRequest'
    ];


    /**
     * 实例化支付模型
     * @param $payType string
     * @return mixed
     */
    protected function getModel(string $payType)
    {
        $className = $this->payTypeModelName[$payType];

        return new $className();
    }

    /**
     * 支付宝支付
     * @param $body string 商品名称
     * @param $out_trade_no string 订单号
     * @param $total_amount float 订单价格
     * @param string $payType 支付方式
     * @param string $return_url WAP支付时的前台支付完成回跳地址
     * @return string
     * @throws \Exception
     */
    public function pay($body, $out_trade_no, $total_amount, $payType = 'APP', string $return_url = '')
    {
        $aop = new AopClient();
        $aliConfig = OrdersLib::getPayConfig('ali');

        $aop->gatewayUrl = $aliConfig['gatewayUrl'];
        $aop->appId = $aliConfig['app_id'];
        $aop->rsaPrivateKey = $aliConfig['merchant_private_key'];
        $aop->format = "json";
        $aop->postCharset = "UTF-8";
        $aop->signType = "RSA2";
        $aop->apiVersion = '1.0';
        $aop->alipayrsaPublicKey = $aliConfig['alipay_public_key'];

        $request = $this->getModel($payType);

        $arr['body'] = $body;
        $arr['subject'] = $body;
        $arr['out_trade_no'] = $out_trade_no;
        $arr['timeout_express'] = '1d';


        $arr['total_amount'] = "$total_amount";
        //        $arr['total_amount'] = 0.01;
        $arr['product_code'] = $payType == 'APP' ? 'QUICK_MSECURITY_PAY' : 'QUICK_WAP_WAY';

        $json = json_encode($arr);

        $request->setNotifyUrl($aliConfig['notify_url']);
        $request->setBizContent($json);

        if ($payType == 'APP') {
            // APP支付
            $response = $aop->sdkExecute($request);
        } else {
            $request->setReturnUrl($return_url);
            // 手机网页支付
            $response = $aop->pageExecute($request);
        }
        //        Log::write('AliPay_Response:'. json_encode($response),'log',true);
        return $response;
    }

    /**
     * 支付宝订单查询
     * 文档地址： https://docs.open.alipay.com/api_1/alipay.trade.query/
     * @param array $data
     * @param int $account 支付宝订单进行查询时，使用的商户配置
     * @return bool|mixed|\SimpleXMLElement
     * @throws \Exception
     */
    public function query($data = [], $account = 0)
    {
        $aliConfig = OrdersLib::getPayConfig('ali', $account);
        $aop = new AopClient();
        $aop->gatewayUrl = $aliConfig['gatewayUrl'];
        $aop->appId = $aliConfig['app_id'];
        $aop->rsaPrivateKey = $aliConfig['merchant_private_key'];
        $aop->alipayrsaPublicKey = $aliConfig['alipay_public_key'];
        $aop->apiVersion = '1.0';
        $aop->signType = 'RSA2';
        $aop->postCharset = 'UTF-8';
        $aop->format = 'json';
        $request = new AppPayQueryRequest();

        $json = json_encode($data);
        $request->setBizContent($json);
        $result = $aop->execute($request);

        return $result;
    }

    /**
     * 支付宝退款
     * 文档地址： https://docs.open.alipay.com/api_1/alipay.trade.refund
     * @param array $data 以下参数必传
     *  out_trade_no string 订单支付时传入的商户订单号,不能和 trade_no同时为空。
     *  refund_amount string 需要退款的金额，该金额不能大于订单金额,单位为元，支持两位小数
     *  refund_reason string 退款的原因说明
     *  operator_id int 商户的操作员编号
     *  out_request_no string 标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传。
     * @param int $account
     * @return bool
     * @throws \Exception
     */
    public function refund($data = [], $account = 0)
    {
        $aliConfig = OrdersLib::getPayConfig('ali', $account);
        $aop = new AopClient();
        $aop->gatewayUrl = $aliConfig['gatewayUrl'];
        $aop->appId = $aliConfig['app_id'];
        $aop->rsaPrivateKey = $aliConfig['merchant_private_key'];
        $aop->alipayrsaPublicKey = $aliConfig['alipay_public_key'];
        $aop->apiVersion = '1.0';
        $aop->signType = 'RSA2';
        $aop->postCharset = 'UTF-8';
        $aop->format = 'json';
        $request = new AlipayTradeRefundRequest();
        $request->setBizContent(json_encode($data));
        $result = $aop->execute($request);

        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";

        $resultCode = $result->$responseNode->code;

        if (!empty($resultCode) && $resultCode == 10000) {
            return true;
        } else {
            return false;
        }
    }
}
